﻿/*****************************************************************************\
 *             University of Illinois/NCSA Open Source License
 *
 * 
 *      Copyright © 2012,2013, The Board of Trustees of the University of Illinois. All rights reserved.
 *
 *      Developed by: Rakesh Bobba, Derek Dagit, Erich Heine, Denis Kholine,
 *                    Klara Nahrstedt, David Rodgers,   William H. Sanders, Tim Yardley
 *
 *      Information Trust Institute/Coordinated Science Laboratory
 * 
 *      University of Illinois
 *      
 *      The Board of Trustees of the University of Illinois
 *      109 Coble Hall
 *      801 South Wright Street
 *      Champaign, IL 61820-6242
 *
 *      http://www.iti.illinois.edu / http://csl.illinois.edu
 * 
 *      Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
 *      associated documentation files (the “Software”), to deal with the Software without restriction, 
 *      including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *      and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
 *      subject to the following conditions:
 *
 *      Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *      following disclaimers.
 *      
 *      Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *      the following disclaimers in the documentation and/or other materials provided with the distribution.
 *
 *      Neither the names of Information Trust institute, Coordinated Science Laboratory, University of Illinois,
 *      The Board of Trustees of the University of Illinois nor the names of its contributors may be used to 
 *      endorse or promote products derived from this Software without specific prior written permission.
 *      
 *      THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 *      LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN
 *      NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 *      SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 *      
 \*****************************************************************************/

 using System;
using System.Collections.Generic;
 using System.Data;
﻿using SIEGate.Core.Configurator;

namespace SIEGate.Core
{
    public abstract class NetworkCommunicator : IDataProcessor
    {
        // Used to be called Configuration.
        public class NetworkCommunicatorInfoBase : ConfigInfo, IDataProcessorInfo, INotificationTarget
        {
            private Dictionary<string, string> m_defaultSettings = new Dictionary<string, string>();
            private Type m_networkCommunicatorType;
            private Dictionary<string, string> m_settings;

            public override Type RuntimeType
            {
                get 
                {
                    return m_networkCommunicatorType;
                }
                set
                {
                    if (typeof(NetworkCommunicator).IsAssignableFrom(value))
                    {
                        m_networkCommunicatorType = value;
                    }
                    else
                    {
                        throw new NotSupportedException("Must assign an NetworkCommunicator to NetworkCommunicatorInfo.RuntimeType");
                    }
                }
            }
           
            public Dictionary<string, string> Settings
            {
                get
                {
                    return m_settings;
            }
                set
                {
                    m_settings = value;
                }
            }

            public override void Update(Dictionary<string, string> configInfo)
            {
                Settings = configInfo;
            }

            public override void ExtractConfiguration(DataSet configurationTables)
            {
                string setting;

                if (Settings.TryGetValue("incomingStreamIDs", out setting))
                    IncomingStreamIDs = GsfHandler.ParseStreamIDs(configurationTables, setting);

                if (Settings.TryGetValue("outgoingStreamIDs", out setting))
                    OutgoingStreamIDs = GsfHandler.ParseStreamIDs(configurationTables, setting);
            }

            public void SetDefaults(Dictionary<string, string> defaults)
            {
                foreach (string key in defaults.Keys)
                    m_defaultSettings[key] = defaults[key];
            }

            public string DefaultGet(string key)
            {
                string res;

                if (!Settings.TryGetValue(key, out res))
                    m_defaultSettings.TryGetValue(key, out res);

                return res;
            }
        }

        // This is protected instead of private so that the Task, DataSubscriber, and DataPublisher can reference it.
        protected IMessageBusProxy MessageBusProxy;
        public NetworkCommunicatorInfoBase Info { get; set; }
        protected Stats.Cluster m_statsCluster;
        public const string StrStatBytesIn = "Bytes In";
        public const string StrStatBytesOut = "Bytes Out";
        protected INotificationReceiver Receiver
        {
            get;
            set;
        }

        // NetworkCommunicators are either inbound or outbound.
        // NetworkCommunicators only get one DataStream.
        protected NetworkCommunicator(IMessageBusProxy busProxy, NetworkCommunicatorInfoBase info)
        {
            MessageBusProxy = busProxy;
            Info = info;
            Receiver = Info.Receiver;
            Info.Receiver = null;
            m_statsCluster = Stats.Stats.StatDispatcher.RegisterCluster(info.ID);

            const uint statSourceId = 0;

            m_statsCluster.RegisterCounter(Info.Name, StrStatBytesOut);
            m_statsCluster.RegisterCounter(Info.Name, StrStatBytesIn);
        }

        //// Events maybe?
        //public abstract RawData Receive();

        public abstract void Start();
        public abstract void Stop();

        public virtual void Register()
        {
            if (Info.OutgoingStreamIDs.Count > 0)
            {
                MessageBusProxy.Publish(Info.OutgoingStreamIDs);
            }
            if (Info.IncomingStreamIDs.Count > 0)
            {
                MessageBusProxy.Subscribe(Info.IncomingStreamIDs);
            }
        }

        protected void UpdateBytesReceived(int bytes)
        {
            m_statsCluster.AddToCounter(StrStatBytesIn, bytes);
        }

        protected void UpdateBytesSent(int bytes)
        {
            m_statsCluster.AddToCounter(StrStatBytesOut, bytes);
        }
    } 
}
